package com.example.chatgpt;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.chatgpt.adapter.MessageAdapter;
import com.example.chatgpt.bean.Message;
import com.example.chatgpt.dao.MessageDao;
import com.example.chatgpt.entity.MessageInfo;
import com.example.chatgpt.util.CloseKeyBoardUtil;
import com.example.chatgpt.util.TimeUtil;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private RecyclerView rv_message;
    private TextView tv_text;
    private EditText et_question;
    private List<Message> messageList;
    private MessageAdapter adapter;

    //导入okhttp
    public static final MediaType JSON
            = MediaType.get("application/json; charset=utf-8");
    OkHttpClient okHttpClient = new OkHttpClient();
    private String apiKey;
    private MessageDao messageDao;
    private EditText et_input_key;
    private SharedPreferences preferences;
    private SharedPreferences.Editor edit;

    //gpt模型选择标志
    private int flag = 0;

    //gpt模型数组
    private String[] modelArray = {
            "text-davinci-003", "gpt-3.5-turbo"
    };

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取控件
        rv_message = findViewById(R.id.rv_message);
        tv_text = findViewById(R.id.tv_text);
        et_question = findViewById(R.id.et_question);
        findViewById(R.id.ib_sent).setOnClickListener(this);
        findViewById(R.id.ib_delete).setOnClickListener(this);
        findViewById(R.id.ib_key).setOnClickListener(this);
        findViewById(R.id.ib_list).setOnClickListener(this);
        findViewById(R.id.ib_select_model).setOnClickListener(this);

        //设置RecycleView的adapter
        messageList = new ArrayList<>();
        adapter = new MessageAdapter(messageList);
        rv_message.setLayoutManager(new LinearLayoutManager(this));
        rv_message.setAdapter(adapter);

        //获取数据库
        MyApplication application = (MyApplication) getApplicationContext();
        messageDao = application.getMessageDao();

        //获取sharedPreference对象用于保存key
        preferences = getSharedPreferences("api_key", Context.MODE_PRIVATE);
        edit = preferences.edit();
        //每次进入页面 加载上次输入的apikey
        //进入页面的弹窗
        reload();
    }

    //进入页面时的弹窗
    private void MyAlertDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("使用须知");
        builder.setIcon(R.mipmap.notify);
        builder.setMessage("1 第一次使用时必须从上方钥匙进入设置你的api-key，设置成功之后以后直接使用即可\n" +
                "2 如需更换api-key点击钥匙进入更换即可\n" +
                "3 点击聊天图标即可进入聊天记录页面，点击查询按钮可以查询某一天的记录\n" +
                "4 聊天页面的清除图标不会清除数据库的数据而聊天记录页面的图标会清除数据库的记录，请谨慎操作\n");
        builder.setPositiveButton("关闭", (dialogInterface, i) -> {
            dialogInterface.dismiss();
        });
        builder.setNegativeButton("不再提示", (dialogInterface, i) -> {
            edit.putInt("flag", 1);
            edit.commit();
            dialogInterface.dismiss();
        });
        builder.create().show();

    }

    //加载apikey
    private void reload() {
        String api_key = preferences.getString("api_key", "");
        if (!api_key.equals("")) {
            apiKey = api_key;
        }
        int flag = preferences.getInt("flag", 0);
        if (flag == 1) {
            return;
        } else {
            MyAlertDialog();
        }
    }

    //发送操作
    //清空操作
    //返回操作
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.ib_sent:
                //关闭软键盘
                CloseKeyBoardUtil.hideOneInputMethod(this, view);
                //获取文本输入框中的问题
                String question = et_question.getText().toString().trim();
                //判空
                if (question.equals("")) {
                    Toast.makeText(this, "铁子 问题不能为空哦~", Toast.LENGTH_SHORT).show();
                    et_question.requestFocus();
                    return;
                } else {
                    //将文本输入框中的问题加入到message列表 并且更新recycleView 展示
                    addToChat(question, Message.SENT_BY_ME);
                    //清空文本输入框
                    et_question.setText("");
                    //将提示文字隐藏
                    tv_text.setVisibility(View.GONE);
                    //请求ChatGPT
                    setCallApi(question, flag);
                }
                break;
            case R.id.ib_delete:
                deleteToChat();
                tv_text.setVisibility(View.VISIBLE);
                break;
            case R.id.ib_key:
                /*Intent intent = new Intent(this, InputApiKeyActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);*/
                initKeyDialog();
                break;
            case R.id.ib_list:
                Intent intent1 = new Intent(this, ChatHistoryActivity.class);
                intent1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent1);
                break;
            case R.id.ib_select_model:
                initModelDialog();
                break;
        }

    }

    //gpt模型底部弹窗
    @SuppressLint("MissingInflatedId")
    private void initModelDialog() {
        Dialog bottomDialog = new Dialog(this, R.style.BottomDialog);
        //获取布局文件
        View view = LayoutInflater.from(this).inflate(R.layout.select_model, null);
        //加入布局
        bottomDialog.setContentView(view);
        //设置参数
        ViewGroup.LayoutParams params = view.getLayoutParams();
        params.width = getResources().getDisplayMetrics().widthPixels;
        bottomDialog.getWindow().setGravity(Gravity.BOTTOM);
        bottomDialog.getWindow().setWindowAnimations(R.style.BottomDialog_Animation);
        bottomDialog.show();
        ListView lv_model = view.findViewById(R.id.lv_model);
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, R.layout.item_moel, R.id.tv_model, modelArray);
        lv_model.setAdapter(arrayAdapter);
        lv_model.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                switch (position) {
                    case 0:
                        flag = 0;
                        break;
                    case 1:
                        flag = 1;
                        break;
                }
                bottomDialog.dismiss();
            }
        });
    }

    //设置模型
    void setCallApi(String question, int flag) {
        switch (flag) {
            case 0:
                callApi(question);
                break;
            case 1:
                callApi1(question);
                break;
        }
    }

    //密钥底部弹窗
    private void initKeyDialog() {
        //创建dialog对象
        Dialog bottomDialog = new Dialog(this, R.style.BottomDialog);
        //获取布局文件
        View view = LayoutInflater.from(this).inflate(R.layout.activity_input_api_key, null);
        //加入布局
        bottomDialog.setContentView(view);
        //设置参数
        ViewGroup.LayoutParams params = view.getLayoutParams();
        params.width = getResources().getDisplayMetrics().widthPixels;
        bottomDialog.getWindow().setGravity(Gravity.BOTTOM);
        bottomDialog.getWindow().setWindowAnimations(R.style.BottomDialog_Animation);
        bottomDialog.show();
        //事件处理
        et_input_key = view.findViewById(R.id.et_input_key);
        view.findViewById(R.id.ib_confirm).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                apiKey = et_input_key.getText().toString().trim();
                //用sharedPreference保存key
                edit.putString("api_key", apiKey);
                edit.commit();
                bottomDialog.dismiss();
            }
        });
    }

    //清空聊天信息
    void deleteToChat() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                messageList.removeAll(messageList);
                adapter.notifyDataSetChanged();
                rv_message.smoothScrollToPosition(adapter.getItemCount());
            }
        });
    }

    //将信息装进messageList中 并更新recycleView
    void addToChat(String message, String sentBy) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                messageList.add(new Message(message, sentBy));
                //将消息加入到数据库
                messageDao.insertMessage(new MessageInfo(message, sentBy, TimeUtil.getDateNow()));
                //更新recycleView
                adapter.notifyDataSetChanged();
                rv_message.smoothScrollToPosition(adapter.getItemCount());
            }
        });
    }

    void addResponse(String response) {
        messageList.remove(messageList.size() - 1);
        //将加入的请求骚等数据删除
        messageDao.deleteByMessage("正在请求 骚等~");
        addToChat(response, Message.SENT_BY_ROBOT);
    }

    //请求ChatGPT
    void callApi(String question) {

        addToChat("正在请求 骚等~", Message.SENT_BY_ROBOT);

        JSONObject jsonBody = new JSONObject();
        try {
            //使用模型
            jsonBody.put("model", "text-davinci-003");
            //问题关键字
            jsonBody.put("prompt", question);
            //回复的最大令牌数
            jsonBody.put("max_tokens", 4000);
            jsonBody.put("temperature", 0.7);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        //创建一个请求表单
        RequestBody requestBody = RequestBody.create(jsonBody.toString(), JSON);

        //创建request请求
        Request request = new Request.Builder()
                //请求地址
                .url("https://api.openai.com/v1/completions")
                //api key
                .header("Authorization", "Bearer " + apiKey)
                //提交表单
                .post(requestBody)
                .build();

        //提交请求 得到response返回报文
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                addResponse("Failed to load response due to " + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    try {
                        JSONObject jsonObject = new JSONObject(response.body().string());
                        JSONArray jsonArray = jsonObject.getJSONArray("choices");
                        String result = jsonArray.getJSONObject(0).getString("text");
                        addResponse(result.trim());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else {
                    addResponse("Failed to load response due to " + response.body().toString());
                }
            }
        });

    }

    //gpt-3.5
    void callApi1(String question) {

        addToChat("正在请求 骚等~", Message.SENT_BY_ROBOT);

        JSONObject jsonBody = new JSONObject();
        JSONObject messageBody = new JSONObject();
        JSONArray messageArr = new JSONArray();
        try {
            //使用模型
            jsonBody.put("model", "gpt-3.5-turbo");
            //问题关键字
            messageBody.put("role", "user");
            messageBody.put("content", question);
            messageArr.put(messageBody);
            jsonBody.put("messages", messageArr);
            //回复的最大令牌数
            jsonBody.put("max_tokens", 4000);
            jsonBody.put("temperature", 0.7);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        //创建一个请求表单
        Log.d("guaimiao", jsonBody.toString());
        RequestBody requestBody = RequestBody.create(jsonBody.toString(), JSON);

        //创建request请求
        Request request = new Request.Builder()
                //请求地址
                .url("https://api.openai.com/v1/chat/completions")
                //api key
                .header("Authorization", "Bearer " + apiKey)
                //提交表单
                .post(requestBody)
                .build();

        //提交请求 得到response返回报文
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("guaimiao", e.getMessage());
                addResponse("Failed to load response due to " + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    try {
                        JSONObject jsonObject = new JSONObject(response.body().string());
                        Log.d("guaimiao", jsonObject.toString());
                        JSONArray choicesArray = jsonObject.getJSONArray("choices");
                        JSONObject item = choicesArray.getJSONObject(0);
                        JSONObject message = item.getJSONObject("message");
                        Log.d("guaimiao", message.toString());
                        String content = message.getString("content");
                        addResponse(content.trim());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else {
                    Log.d("guaimiao", response.body().string());
                    addResponse("Failed to load response due to " + response.body().toString());
                }
            }
        });

    }
}